﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace VPSoftTestApplication.Common
{
    public class CustomBindingList<T> : BindingList<T>
    {
        private bool _isSorted;
        private ListSortDirection _sortDirection = ListSortDirection.Ascending;
        private PropertyDescriptor _sortProperty;
        private bool _autoSort = false;

        public bool AutoSort
        {
            get { return _autoSort; }
            set { _autoSort = value; }
        }

        public CustomBindingList(List<T> elements)
            : base(elements)
        {
        }
        
        public CustomBindingList(List<T> elements, bool autoSort)
            : base(elements)
        {
            _autoSort = autoSort;
        }

        public void SetElements(List<T> elements)
        {
            base.ClearItems();
            foreach (var element in elements)
            {
                Add(element);
            }
        }

        protected override bool SupportsSortingCore
        {
            get { return true; }
        }

        protected override bool IsSortedCore
        {
            get { return _isSorted; }
        }

        protected override ListSortDirection SortDirectionCore
        {
            get
            {
                return _sortDirection;
            }
        }

        protected override PropertyDescriptor SortPropertyCore
        {
            get { return _sortProperty; }
        }

        protected override void RemoveSortCore()
        {
            _sortDirection = ListSortDirection.Ascending;
            _sortProperty = null;
        }

        protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
        {
            _isSorted = true;
            _sortDirection = direction;
            _sortProperty = prop;
            if (!_autoSort)
                return;

            if (_sortProperty == null) return; //nothing to sort on
            List<T> list = Items as List<T>;
            if (list == null) 
                return;
            list.Sort(Compare);
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

        private int Compare(T lhs, T rhs)
        {
            object lhsValue = lhs == null ? null : _sortProperty.GetValue(lhs);
            object rhsValue = rhs == null ? null : _sortProperty.GetValue(rhs);
            int result = 0;
            if (rhsValue == null && lhsValue == null)
            {
                result = 0;
            }
            else
            {
                if (lhsValue == null)
                {
                    result = -1;
                }
                else if (rhsValue == null)
                {
                    result = 1;
                }
                else
                {
                    if (lhsValue is IComparable)
                    {
                        result = ((IComparable)lhsValue).CompareTo(rhsValue);
                    }
                    else if (!lhsValue.Equals(rhsValue))
                    {
                        result = lhsValue.ToString().CompareTo(rhsValue.ToString());
                    }
                }
            }
            if (_sortDirection == ListSortDirection.Descending)
                result = -result;
            return result;
        }
    }
}
